import tool from "@/utils/tool";
import api from "@/http/api";
import date from "@/utils/date";
import { store as pinia } from "@/pinia";
import { useUserStore } from "@/pinia/modules/user";

const userStore = useUserStore(pinia);

export const initStyle = (node, styleId) => {
  node.currStyle = {};
  node.currCompStyle = {};

  let style;
  if (!node.styleList || node.styleList.length === 0) {
    style = {};
  } else if (!styleId) {
    style = node.styleList[0];
  } else {
    for (const item of node.styleList) {
      if (item.id === styleId) {
        style = item;
        break;
      }
    }
  }

  if (!style) {
    style = node.styleList[0];
  }

  node.currStyle = style.style || {};
  node.currCompStyle = style.compStyle || {};
};

export const parseFontStyle = (styleJson, defaultValue, prefix) => {
  if (!styleJson) return defaultValue || '';

  const json = Object.assign(tool.deepClone(styleJson), defaultValue || {});
  let result = '';

  result += parseTplNs('font-size: {value};', json[(prefix || '') + 'fontSize'], 'px');
  result += parseTpl('letter-spacing: {value};', json[(prefix || '') + 'letterSpacing']);
  if (json[(prefix || '') + 'lineHeight']) {
    result += parseTpl('line-height: {value};', json[(prefix || '') + 'lineHeight']);
  }
  result += parseTpl('font-family: {value};', json[(prefix || '') + 'fontFamily']);
  result += parseTpl('font-weight: {value};', json[(prefix || '') + 'fontWeight']);
  result += parseTpl('color: {value};', json[(prefix || '') + 'fontColor']);
  result += parseTpl('cursor: {value};', json[(prefix || '') + 'cursor']);

  return result;
};

/**
 * 将json格式样式转换成字符串格式
 * @param styleJson
 * @param defaultValue
 */
export const parseStyle = (styleJson, defaultValue) => {
  if (!styleJson) return defaultValue || '';

  const json = Object.assign(tool.deepClone(styleJson), defaultValue || {});

  let result = parseFontStyle(styleJson, defaultValue);

  if (json['bgMode'] === '图片' && json['imageId']) {
    let url = window.location.origin + import.meta.env.VITE_IMAGE_PATH + json['imageId'];
    result += parseTpl('background-image: url({value});', url);
    result += parseTpl('background-repeat: {value};', json['background-repeat']);
    result += parseTpl('background-size: {value};', json['background-size']);
    result += parseTpl('background-position: {value};', json['background-position']);
    result += parseTpl('background-color: {value};', json['background-color']);
  } else if (json['bgMode'] === '线性') {
    if (json['start-color'] && json['end-color'] && json['gradient-direction']) {
      result += 'background-image: linear-gradient('
          + json['gradient-direction'] + ', '
          + json['start-color'] + ', '
          + json['end-color'] + ');';
    }
  } else if (json['bgMode'] === '径向') {
    if (json['start-color'] && json['end-color'] && json['gradient-shape']) {
      result += 'background-image: radial-gradient('
          + json['gradient-shape'] + ', '
          + json['start-color'] + ', '
          + json['end-color'] + ');';
    }
  } else if (json['bgMode'] === '颜色') {
    result += parseTpl('background-color: {value};', json['background-color']);
  }

  result += parseTplNs('filter: blur({value});', json['filter'], 'px');
  result += parseTpl('display: {value};', json['display']);

  if (json['display'] === 'flex') {
    result += parseTpl('flex-direction: {value};', json['flex-direction']);
    result += parseTpl('justify-content: {value};', json['justify-content']);
    result += parseTpl('align-items: {value};', json['align-items']);
    result += parseTpl('flex-wrap: {value};', json['flex-wrap']);
  }

  result += parseTpl('flex-grow: {value};', json['flex-grow']);
  result += parseTpl('flex-shrink: {value};', json['flex-shrink']);
  result += parseTpl('position: {value};', json['position']);

  if (json['position'] && json['position'] !== 'static') {
    const positionMargin = (json['position-margin'] || '0,,,0').split(',');
    if (positionMargin.length >= 4) {
      result += parseTplNs('top: {value};', positionMargin[0], 'px');
      result += parseTplNs('right: {value};', positionMargin[1], 'px');
      result += parseTplNs('bottom: {value};', positionMargin[2], 'px');
      result += parseTplNs('left: {value};', positionMargin[3], 'px');
    }
    result += parseTpl('z-index: {value};', json['z-index']);
  }

  if (json['margin'] && json['margin'] !== '0,0,0,0') {
    const margin = (json['margin'] || '0,0,0,0').split(',');
    result += parseTplNs('margin-top: {value};', margin[0], 'px');
    result += parseTplNs('margin-right: {value};', margin[1], 'px');
    result += parseTplNs('margin-bottom: {value};', margin[2], 'px');
    result += parseTplNs('margin-left: {value};', margin[3], 'px');
  }

  if (json['padding'] && json['padding'] !== '0,0,0,0') {
    const padding = (json['padding'] || '0,0,0,0').split(',');
    result += parseTplNs('padding-top: {value};', padding[0], 'px');
    result += parseTplNs('padding-right: {value};', padding[1], 'px');
    result += parseTplNs('padding-bottom: {value};', padding[2], 'px');
    result += parseTplNs('padding-left: {value};', padding[3], 'px');
  }

  result += parseTpl('width: {value};', json['width']);
  result += parseTpl('height: {value};', json['height']);
  result += parseTpl('overflow: {value};', json['overflow']);

  if (json['radius-type'] === 'simple') {
    result += parseTplNs('border-radius: {value};', json['border-radius'], 'px');
  } else if (json['radius-type'] === 'complex') {
    result += parseTplNs('border-top-left-radius: {value};', json['border-top-left-radius'], 'px');
    result += parseTplNs('border-top-right-radius: {value};', json['border-top-right-radius'], 'px');
    result += parseTplNs('border-bottom-right-radius: {value};', json['border-bottom-right-radius'], 'px');
    result += parseTplNs('border-bottom-left-radius: {value};', json['border-bottom-left-radius'], 'px');
  }
  if (json['border-type'] === 'simple') {
    result += parseTpl('border-style: {value};', json['border-style']);
    result += parseTplNs('border-width: {value};', json['border-width'], 'px');
    result += parseTpl('border-color: {value};', json['border-color']);
  } else if (json['border-type']) {
    if (json['border-top-width']) {
      result += parseTpl('border-top-style: {value};', json['border-top-style']);
      result += parseTplNs('border-top-width: {value};', json['border-top-width'], 'px');
      result += parseTpl('border-top-color: {value};', json['border-top-color']);
    }
    if (json['border-right-width']) {
      result += parseTpl('border-right-style: {value};', json['border-right-style']);
      result += parseTplNs('border-right-width: {value};', json['border-right-width'], 'px');
      result += parseTpl('border-right-color: {value};', json['border-right-color']);
    }
    if (json['border-bottom-width']) {
      result += parseTpl('border-bottom-style: {value};', json['border-bottom-style']);
      result += parseTplNs('border-bottom-width: {value};', json['border-bottom-width'], 'px');
      result += parseTpl('border-bottom-color: {value};', json['border-bottom-color']);
    }
    if (json['border-left-width']) {
      result += parseTpl('border-left-style: {value};', json['border-left-style']);
      result += parseTplNs('border-left-width: {value};', json['border-left-width'], 'px');
      result += parseTpl('border-left-color: {value};', json['border-left-color']);
    }
  }

  if (json['opacity'] !== 1) {
    result += parseTpl('opacity: {value};', json['opacity']);
  }
  if (json['cursor'] !== 'default') {
    result += parseTpl('cursor: {value};', json['cursor']);
  }

  if (json['box-shadow-style'] !== 'none') {
    if (json['box-shadow-horizontal']
        || json['box-shadow-vertical']
        || json['box-shadow-blur']
        || json['box-shadow-spread']) {
      let boxShadow = 'box-shadow: ';
      if (json['box-shadow-style']) {
        boxShadow += json['box-shadow-style'] + ' ';
      }
      boxShadow += (json['box-shadow-horizontal'] + 'px ') || '0 ';
      boxShadow += (json['box-shadow-vertical'] + 'px ') || '0 ';
      boxShadow += (json['box-shadow-blur'] + 'px ') || '0 ';
      boxShadow += (json['box-shadow-spread'] + 'px ') || '0 ';
      boxShadow += (json['box-shadow-color'] || '#ffffff ') + ' ';
      result += boxShadow + ';';
    }
  }
  if (json['gap']) {
    result += parseTpl('gap: {value};', json['gap']);
  }
  result += json['extendCss'] ? json['extendCss'] : '';
  return result;
};

export const parseTpl = (template, value) => {
  if (!value) return '';

  return template.replace('{value}', value + '');
};

export const parseTplNs = (template, value, suffix) => {
  if (typeof value === 'undefined' || value == null || value === '') return '';

  value += '';
  if (suffix && /^[-+]?\d+$/.test(value)) {
    value += suffix;
  }

  return template.replace('{value}', value);
};

export const addIfNotNull = (targetData, sourceData, sourceField) => {
  addIfNotNull2(targetData, sourceField, sourceData, sourceField);
};

export const addIfNotNull2 = (targetData, targetField, sourceData, sourceField) => {
  if (sourceData
      && (sourceData[sourceField]
          || sourceData[sourceField] === false
          || sourceData[sourceField] === 0)) {
    targetData[targetField] = sourceData[sourceField];
  }
};

const getConditionStyle = (styleList, data) => {
  for (const style of styleList) {
    let result = false;
    if (!style.conditionList || style.conditionList.length === 0) {
      result = true;
    } else {
      (tool.groupBy(style.conditionList || [], (item) => [item.grouping || 999]) || []).forEach(conditionList => {
        result = result || checkConditionList(conditionList, data);
      });
    }
    if (result) {
      return style;
    }
  }
  return null;
};

const checkConditionList = (conditionList, data) => {
  let result = true;
  (conditionList || []).forEach(condition => {
    const testValue = data[condition.condition];
    switch(condition.type) {
      case "包含":
        result = result && (testValue || '').indexOf(condition.value || '') >= 0;
        break;
      case "不包含":
        result = result && (testValue || '').indexOf(condition.value || '') === -1;
        break;
      case "等于":
        result = result && (testValue || '') === (condition.value || '');
        break;
      case "不等于":
        result = result && (testValue || '') !== (condition.value || '');
        break;
      case "大于":
        result = result && parseFloat(testValue || '0') > parseFloat(condition.value || '0');
        break;
      case "大于等于":
        result = result && parseFloat(testValue || '0') >= parseFloat(condition.value || '0');
        break;
      case "小于":
        result = result && parseFloat(testValue || '0') < parseFloat(condition.value || '0');
        break;
      case "小于等于":
        result = result && parseFloat(testValue || '0') <= parseFloat(condition.value || '0');
        break;
    }
  });
  return result;
};

export const createNode = (name, comp) => {
  return {
    id: tool.uuids(),
    type: comp.type || '',
    name: name || '',
    formItem: comp.formItem || '0',
    styleList: [{
      id: tool.uuids(),
      name: '原始状态',
      style: {
        'background-color': comp.type === 'page' ? comp.background || '#FFFFFF' : null,
        'position': comp.position || '',
        'margin-top': comp.type === 'form' ? '15' : null,
        'padding-right': comp.type === 'form' ? '60' : null,
        'width': comp.width || '',
        'height': comp.height || '',
        'display': comp.display || '',
        'flex-direction': comp['flex-direction'] || '',
        'justify-content': comp['justify-content'] || '',
        'align-items': comp['align-items'] || '',
      },
      compStyle: {},
    }],
    default: comp.defaultObject || false,
    inputParamList: [],
    compData: {
      dataSourceType: ''
    },
    compEventList: [],
    children: []
  }
};

export const loadValue = async(node, event, useGlobal) => {
  if (!node || !event) return '';

  let result = '';
  if (node.currCompStyle) {
    if (node.currCompStyle.defaultType === 'input') {
      result = node.currCompStyle.defaultValue || '';
    } else if (node.currCompStyle.defaultType === 'param') {
      if (typeof useGlobal === 'undefined' || useGlobal) {
        const param = event.getGlobalParam && event.getGlobalParam() || {};
        result = param ? (param[node.currCompStyle.defaultValue] || '') : '';
      }
    } else if (node.currCompStyle.defaultType === 'script') {
      if (node.currCompStyle.defaultValue) {
        const res = await api.runScript(node.currCompStyle.defaultValue);
        result = res && res.data || '';
      } else {
        result = '';
      }
    } else if (node.currCompStyle.defaultValue) {
      result = node.currCompStyle.defaultValue;
    }
  }

  if (!result
      && node.currCompStyle
      && (node.currCompStyle['default'] === 0 || node.currCompStyle['default'])) {
    result = node.currCompStyle['default'];
  }

  if (!result && node.defaultObject) {
    result = node.defaultObject.input ? node.defaultObject.value : '';
  }

  return await parseSymbol(result);
};

export const loadData = async(compData, event, nodeData, node) => {
  if (compData.dataSourceType === '静态数据') {
    if (!compData.dataJson) return [];
    return {data: convertData(compData, JSON.parse(compData.dataJson))};
  } else if (compData.dataSourceType === '输入参数') {
    if (!compData.inputParamList || compData.inputParamList.length === 0) return [];
    const param = Object.assign(
        {},
        event.getGlobalParam && event.getGlobalParam(),
        nodeData,
        nodeData.inputParam || {});
    const paramData = compData.inputParamList[0];
    const value = (paramData.input ? paramData.value : param[paramData.id]) || '';
    const data = Object.assign({'内容': value}, filterData(compData, event, nodeData));

    const item = {};
    for (let i=0; i<compData.inputParamList.length; i++) {
      const paramDataItem = compData.inputParamList[i];
      const valueItem = (paramDataItem.input ? paramDataItem.value : param[paramDataItem.id]) || '';
      const dataItem = Object.assign({'内容': valueItem}, filterData(compData, event, nodeData));
      if (paramDataItem.name) {
        item[paramDataItem.name] = dataItem['内容'] || '';
      }
    }
    return {data: [Object.assign({}, convertData(compData, data)[0], item)]};
  } else if (compData.dataSourceType === '数据模型' || compData.dataSourceType === '视图') {
    if (!compData.dataModelId) return [];
    const url = '/codeless/data-model/' + compData.dataModelId + '/page';
    const res = await api.post(url, {
      pageNumber: nodeData.pageNumber || 1,
      pageSize: nodeData.pageSize || 10,
      sortField: nodeData.sortField,
      sortType: nodeData.sortType,
      ...filterData(compData, event, nodeData),
      filterList: filterFilter(tool.deepClone(compData.filterList)),
      ordinalList: nodeData.sortField ? [] : compData.ordinalList
    });
    const fieldRes = await api.post('/business/data-field/list/' + compData.dataModelId);
    const result = Object.assign({}, res, {data: []});
    result.data = convertData(compData, res.data, fieldRes.data || []);
    result.totalPage = res.totalPage || 0;
    result.totalRecord = res.totalRecord || 0;
    return result;
  } else if (compData.dataSourceType === '脚本') {
    if (!compData.scriptId) return {data: []};
    const res = await api.runScript(compData.scriptId, filterData(compData, event, nodeData));
    if (!res || !res.data || res.data.length === 0) return;
    const result = Object.assign({}, res, {data: []});
    result.data = convertData(compData, res.data);
    result.totalPage = res.totalPage || 0;
    result.totalRecord = res.totalRecord || 0;
    return result;
  } else {
    return {data: [{'内容': await loadValue(node, event, true)}]};
  }
};

const convertData = (compData, data, fieldList) => {
  if (!data
      || (Array.isArray(data) && data.length === 0)
      || (!Array.isArray(data) && Object.keys(data).length === 0)) return [];
  let dataList = Array.isArray(data) ? data : [data || {}];
  if (!compData.fieldList || compData.fieldList.length === 0) return dataList;

  const resultList = [];
  dataList.forEach(data => {
    const result = {};
    compData.fieldList.forEach(mapping => {
      const field = fieldList && fieldList.length > 0 ? fieldList.find(field => field.fieldName === mapping['value']) : null;
      if (field) {
        if (field.fieldType === '联动' && !field.relevanceType.startsWith('字典')) {
          result[mapping['name']] = getValue(data[field.fieldName + '_name']);
        } else if (field.fieldType === '时间') {
          result[mapping['name']] = date.formatLongDate(data[field.fieldName]);
        } else {
          result[mapping['name']] = getValue(data[field.fieldName]);
        }
      } else {
        if (mapping['value'] && mapping['type'] === '日期') {
          result[mapping['name']] = date.formatLongDate(data[mapping['value']] || '', 'yyyy-MM-dd');
        } else if (mapping['value'] && mapping['type'] === '时间') {
          result[mapping['name']] = date.formatLongDate(data[mapping['value']] || '', 'yyyy-MM-dd HH:mm:ss');
        } else {
          result[mapping['name']] = getValue(data[mapping['value']]);
        }
      }
    });
    resultList.push(result);
  });
  return resultList;
};

const getValue = (value) => {
  return typeof value === 'undefined' || value == null ? '' : value;
};

const filterData = (compData, event, nodeData) => {
  if (compData && compData.filterList) {
    const result = {};
    compData.filterList.forEach(filter => {
      if (!filter.fieldId || !filter.compareValue) return;

      if (filter.manually) {
        result[filter.fieldId] = filter.compareValue || '';
      } else if (event && (event.getNodeData || nodeData)) {
        const paths = filter.compareValue.split(".");
        if (paths.length === 0) return;
        const data = event.getNodeData ? event.getNodeData(paths[0]) : nodeData;
        if (paths.length === 2 && paths[1] === 'value') {
          result[filter.fieldId] = data[paths[1]] || '';
        } else if (paths.length === 2 && paths[0] === 'inputParam') {
          result[filter.fieldId] = nodeData[paths[0]]?.[paths[1]] || '';
        } else if (paths.length === 3 && paths[1] === 'inputParam') {
          result[filter.fieldId] = data[paths[1]] ? data[paths[1]][paths[2]] : '';
        }
      }
    });
    return result;
  }

  return {};
};

const filterFilter = (filterList) => {
  const resultList = [];
  (filterList || []).forEach(filter => {
    if (!filter.manually && filter.compareValue && filter.compareValue.indexOf(".")) {
      const paths = filter.compareValue.split(".");
      filter.compareValue = paths[paths.length - 1];
    }
    resultList.push(filter);
  });
  return resultList;
};

const getInputParam = (node, data) => {
  if (!node || !data) return {};

  if (node?.compData?.inputParamList?.length > 0) {
    const inputParam = {};
    node.compData.inputParamList.forEach(param => {
      if (!param.value) return;

      if (param.input) {
        inputParam[param.id] = param.value || '';
      } else if (param.value.indexOf('.') >= 0) {
        if (param.value.endsWith('.row') && !param.value.endsWith('.row.row')) {
          inputParam[param.id] = JSON.stringify(data[param.value] || {});
        } else {
          const key = param.value.substring(0, param.value.lastIndexOf('.'));
          const valueKey = param.value.substring(param.value.lastIndexOf('.') + 1);
          inputParam[param.id] = data[key]?.[valueKey] || '';
        }
      } else {
        inputParam[param.id] = data[param.value] || '';
      }
    });
    return inputParam;
  } else {
    return data;
  }
};

const parseSymbol = async(val) => {
  return await userStore.parseSymbol(val);
}

export default {
  initStyle,
  parseStyle,
  parseFontStyle,
  parseTpl,
  parseTplNs,
  addIfNotNull,
  addIfNotNull2,
  getConditionStyle,
  createNode,
  loadValue,
  loadData,
  getInputParam,
  parseSymbol
};